package org.javaongems.client.vcl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.javaongems.client.rt.awt.Rectangle;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;

public class OpaqueSelection implements DomConstants {
	protected ArrayList selections = new ArrayList();
	protected HashMap selectionsMap = new HashMap();
	protected Element parent;
	public boolean moving, resizing; 
	
	public int startX, startY, currX, currY;
	
	public void attach(Element canvas) {
		if (parent == canvas)
			return;
		detach();
		parent = canvas;
	}
	
	public void detach() {
		if (parent == null)
			return;
		disjoinAll();
		parent = null;
	}
	
	public boolean isAttached() {
		return parent != null;
	}

	public void joinAll() {
		for (Iterator iter = selections.iterator(); iter.hasNext();) {
			Selection sel = (Selection) iter.next();
			sel.join();
			sel.refresh();
		}
	}
	
	public void disjoinAll() {
		for (Iterator iter = selections.iterator(); iter.hasNext();) {
			Selection sel = (Selection) iter.next();
			sel.disjoin();
		}
	}
	
	public Selection add(Object hndl, Rectangle r) {
		Selection ret = new Selection(hndl, r);
		add(ret);
		return ret;
	}
	
	public Selection add(Selection slnt) {
		selections.add(slnt);
		selectionsMap.put(slnt.handle, slnt);
		return slnt;
	}
	
	public Selection remove(Object hndl) {
		Selection ret = (Selection) selectionsMap.remove(hndl);
		selections.remove(ret);
		return ret;
	}
	
	public void reset(int x, int y) {
		startX = x; 
		startY = y;
		currX = startX;
		currY = startY;
	}
	
	public void move(int x, int y) {
		if (x == currX && y == currY)
			return;
		int deltaX = x - currX;
		int deltaY = y - currY;
		currX = x; currY = y;
		for (Iterator iter = selections.iterator(); iter.hasNext();) {
			Selection sel = (Selection) iter.next();
			sel.move(deltaX, deltaY);
		}
	}
	
	public void resize(int x, int y) {
		if (x == currX && y == currY)
			return;
		int deltaX = x - currX;
		int deltaY = y - currY;
		currX = x; currY = y;
		for (Iterator iter = selections.iterator(); iter.hasNext();) {
			Selection sel = (Selection) iter.next();
			sel.resize(deltaX, deltaY);
		}
	}
	
	public List list() {
		return selections;
	}
	
	public Map map() {
		return selectionsMap;
	}
	
	public boolean hadActivity() {
		return moving || resizing;
	}
	
	public class Selection {
		public Rectangle bounds = new Rectangle();
		public Object handle;
		public Element representation;
		public boolean joined;
		
		public Selection(Object hndl, Rectangle rect) {
			bounds.setBounds(rect);
			handle = hndl;
			representation = DOM.createDiv();
			decorateOutline();
		}
		
		public void join() {
			if (!joined) {
				DOM.appendChild(parent, representation);
				joined = true;
			}
		}
		
		public void disjoin() {
			if (joined) {
				DOM.removeChild(parent, representation);
				joined = false;
			}
		}
		
		public void move(int deltaX, int deltaY) {
			bounds.translate(deltaX, deltaY);
			refresh();
		}
		
		public void resize(int deltaX, int deltaY) {
			bounds.setSize(bounds.width + deltaX, bounds.height + deltaY);
			refresh();
		}
		
		public void refresh() {
//			DOM.setStyleAttribute(representation, STYLE_TOP, bounds.y + "px");
//			DOM.setStyleAttribute(representation, STYLE_LEFT, bounds.x + "px");
//			DOM.setStyleAttribute(representation, STYLE_WIDTH, bounds.width + "px");
//			DOM.setStyleAttribute(representation, STYLE_HEIGHT, bounds.height + "px");
			ControlDomRenderer.setTopPosition(representation, bounds.y);
			ControlDomRenderer.setLeftPosition(representation, bounds.x);
			ControlDomRenderer.setPixelWidth(representation, bounds.width);
			ControlDomRenderer.setPixelHeight(representation, bounds.height);
		}
		
		protected void decorateOutline() {
//			DOM.setStyleAttribute(representation, STYLE_POSITION, POSITION_ABSOLUTE);
			DOM.setStyleAttribute(representation, STYLE_OUTLINE_STYLE, "solid");
			DOM.setStyleAttribute(representation, STYLE_OUTLINE_COLOR, "invert");
			DOM.setStyleAttribute(representation, STYLE_OUTLINE_WIDTH, "thin");
			DOM.setStyleAttribute(representation, STYLE_BORDER_STYLE, "dotted");
			DOM.setStyleAttribute(representation, STYLE_BORDER_WIDTH, "thin");
			ControlDomRenderer.setPositionStyle(representation, POSITION_ABSOLUTE);
			ControlDomRenderer.setZindex(representation, 999);
		}
	}
}
